/**
 *    @file       toolkit.h
 *
 *    @brief      
 *    @details
 *
 *    @version    1.0
 *    @date       12/11/2012 11:54:26 PM
 *
 *    @author     Theophilus, wangtf418@gmail.com
 */
#ifndef _BF_TOOLKIT_H_
#define _BF_TOOLKIT_H_
#include <string>
#include <vector>
#include <list>
#include <map>
#include <sys/time.h>
#include "comdef.h"

class toolkit
{
public:
	toolkit();
	~toolkit();

//string toolkit
public:
	//string process
	static bf_size_t sub_string(const bf_char_t *src_string, bf_size_t str_len, const std::string &sep);
	static bf_int_t split_string_by_line(const bf_char_t *src_string, bf_size_t str_len, std::vector<bf_string_t> &str_arr_out);
	static bf_int_t split_string_by_string(const char *src_string, bf_size_t str_len, const std::string &sep, std::vector<bf_string_t> &str_arr_out, bf_bool_t emptystr = false);
	static bf_int_t split_string_by_chars(const char *src_string, bf_size_t str_len, const std::string &charset, std::vector<bf_string_t> &str_arr_out);
	static void trim_string(std::string &str, const std::string &char_list = " \t\r\n");
	static void trim_string(bf_string_t &str, const std::string &char_list = " \t\r\n");
	static bf_int_t get_string_by_label(const std::string &str, bf_size_t offset, const std::string &label_begin, const std::string &label_end, std::string &str_out, bf_size_t &pos_out, bf_bool_t ignores_case = false);
	//type conversion
	static std::string int2str(bf_int64_t num);
	static bf_int64_t str2int(const bf_char_t *str);
	static bf_int_t str2int(const bf_char_t *str, bf_int64_t &num_out);
	static bf_bool_t is_ipstring(const std::string &str);
	static std::string inaddr2str(bf_uint_t inaddr);
	static bf_uint_t str2inaddr(const std::string &str);
	static bf_int_t str2inaddr(const std::string &str, bf_uint_t &inaddr_out);
	static bf_int_t str_upper2lower(bf_char_t *str, bf_size_t strlen);
	static bf_int_t str_lower2upper(bf_char_t *str, bf_size_t strlen);
	static bf_uint64_t hex2int(const bf_char_t *str, bf_size_t strlen);
	static bf_int_t hex2int(const bf_char_t *str, bf_size_t strlen, bf_uint64_t &num_out);
	static std::string int2hex(bf_uint64_t num, bf_basic_wordlen_t wordlen = BF_BASIC_WLEN0);
	static bf_uint32_t short_elf_hash(const bf_char_t *str, bf_size_t strlen);

	//string conversion
	static std::string hex2bi(const bf_char_t *str, bf_size_t strlen);
	static std::string bi2hex(const bf_char_t *str, bf_size_t strlen);

//time tookit
public:
	static bf_time_t get_unixtime();
	static bf_int_t get_unixtime(bf_time_t &sec, bf_time_t &usec);
	static void get_monotonic_time(bf_time_t &sec, bf_long_t &nsec);
	static void sec2time(bf_time_t unixtime, bf_tm_t &time_out);
	static std::string sec2time(bf_time_t unixtime);
	static std::string sec2formattime(bf_time_t unixtime);
	static std::string sec2httptime(bf_time_t unixtime, std::string tz_type = "GMT");

	static bf_time_t time2sec(const bf_tm_t &time);
	static bf_time_t time2sec(const std::string &time);			///< YYYYMMDDHHMMSS
	static bf_time_t formattime2sec(const std::string &time);	///< YYYY-MM-DD HH:MM:SS
	static bf_time_t httptime2sec(const std::string &time);		///< Wed, 12 Feb 2014 10:57:48 GMT
	static void usleep_byselect(bf_time_t sec, bf_time_t usec);

//file toolkit
public:
	static std::string get_workdir();
	static bf_int_t get_filelist(const std::string &dir, std::vector<std::string> &filelist, std::string suffix = "");

//net toolkit
public:
	static bf_int_t parsedomain(const std::string &domain, std::vector<bf_uint32_t> &iplist);

//math toolkit
public:
	static void srand();
};

static const bf_char_t * BF_MONTH_STRING[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static const bf_char_t * BF_WEEK_STRING[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

class time_trans_base
{
public:
	time_trans_base()
	{
		for (bf_int_t i = 0; i < 12; i ++)
		{
			m_month.insert(make_pair(std::string(BF_MONTH_STRING[i]), i));
		}
		for (bf_int_t i = 0; i < 7; i ++)
		{
			m_week.insert(make_pair(std::string(BF_WEEK_STRING[i]), i));
		}
		struct timeval tm_val;
		struct timezone tm_zone;
		gettimeofday(&tm_val, &tm_zone);
		m_timezone = tm_zone.tz_minuteswest * 60;
	}

public:
	inline bf_int_t findmonth(const std::string &str) const
	{
		std::map<std::string, bf_int_t>::const_iterator itr = m_month.find(str);
		if (itr != m_month.end())
		{
			return itr->second;
		}
		return -1;
	}

	inline bf_int_t findweek(const std::string &str) const
	{
		std::map<std::string, bf_int_t>::const_iterator itr = m_week.find(str);
		if (itr != m_week.end())
		{
			return itr->second;
		}
		return -1;
	}

	inline bf_time_t get_timezone() const
	{
		return m_timezone;
	}

private:
	std::map<std::string, bf_int_t> m_month; 
	std::map<std::string, bf_int_t> m_week;
	bf_time_t m_timezone;
};

#endif

